package com.zros.config;

import java.util.List;

import org.apache.shiro.authz.UnauthorizedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import com.zros.common.api.vo.Result;
import com.zros.common.constant.Constant;
import com.zros.common.constant.ResponseConstant;
import com.zros.common.exception.JeecgBootException;
import com.zros.common.exception.ParamJsonException;

/**
 * @ClassName: AllControllerAdvice
 * @Description: Controller统一异常处理
 * 
 * @date 2018年5月18日 下午5:13:32
 */
@ControllerAdvice(basePackages = "com.zros")
public class BootControllerAdvice {

	private static Logger logger = LoggerFactory.getLogger(BootControllerAdvice.class);

	/**
	 * 应用到所有@RequestMapping注解方法，在其执行之前初始化数据绑定器
	 */
	@InitBinder
	public void initBinder(WebDataBinder binder) {
	}

	/**
	 * 把值绑定到Model中，使全局@RequestMapping可以获取到该值
	 */
	@ModelAttribute
	public void addAttributes(Model model) {
	}

	/**
	 * 全局异常捕捉处理
	 */
	@ExceptionHandler(value = Exception.class)
	@ResponseBody
	public Result<?> errorHandler(Exception e) {
		logger.error("接口出现严重异常：", e);
		return new Result<String>().error(ResponseConstant.ERROR);
	}

	/**
	 * 捕捉UnauthorizedException,当前用户没权限
	 * 
	 * @return
	 */
	@ResponseStatus(HttpStatus.OK)
	@ExceptionHandler(UnauthorizedException.class)
	@ResponseBody
	public Result<?> handle4011() {
		return new Result<String>().error(ResponseConstant.USER_NO_PERMITION);
	}

	/**
	 * 捕捉UnauthorizedException
	 * 
	 * @return
	 *//*
		 * @ResponseStatus(HttpStatus.OK)
		 * 
		 * @ExceptionHandler(UnauthorizedException.class)
		 * 
		 * @ResponseBody public Result<?> handle401() { return new
		 * Result<String>().error(ResponseConstant.USER_NO_PERMITION); }
		 */

	/**
	 * 捕捉shiro的异常
	 * 
	 * @param e
	 * @return
	 *//*
		 * @ResponseStatus(HttpStatus.OK)
		 * 
		 * @ExceptionHandler(ShiroException.class)
		 * 
		 * @ResponseBody public Result<?> handle401(ShiroException e) { return new
		 * Result<String>().error(ResponseConstant.UNAUTHORIZED); }
		 */

	/**
	 * 认证失败，未登录或者token过期
	 * 
	 * @param e
	 * @return
	 *//*
		 * @ResponseStatus(HttpStatus.OK)
		 * 
		 * @ExceptionHandler(ShiroException.class)
		 * 
		 * @ResponseBody public Result<?> handle401(UnauthenticatedException e) { return
		 * new Result<String>().error(ResponseConstant.UNAUTHORIZED); }
		 */

	@ResponseStatus(HttpStatus.OK)
	@ExceptionHandler(value = ParamJsonException.class)
	@ResponseBody
	public Result<?> handleParam(Exception e) {
		if (e instanceof ParamJsonException) {
			logger.error("参数错误：" + e.getMessage());
			return new Result<String>().error(ResponseConstant.PARAM_ERROR);
		}
		return new Result<String>().error();
	}

	@ResponseStatus(HttpStatus.OK)
	@ExceptionHandler(value = JeecgBootException.class)
	@ResponseBody
	public Result<?> handleBuiness(JeecgBootException e) {
		logger.error("业务逻辑错误：" + e.getMessage());
		return new Result<String>().error(e.getMessage());
	}

	/**
	 * 处理实体字段校验不通过异常
	 * 
	 * @param ex
	 * @return
	 */
	@ResponseStatus(HttpStatus.OK)
	@ExceptionHandler(MethodArgumentNotValidException.class)
	@ResponseBody
	public Result<String> validationError(MethodArgumentNotValidException e) {
		logger.info("参数校验不通过 : " + e.getMessage());
		BindingResult result = e.getBindingResult();
		final List<FieldError> fieldErrors = result.getFieldErrors();
		StringBuilder builder = new StringBuilder();
		int i = Constant.Number.ZERO;
		for (FieldError error : fieldErrors) {
			i++;
			builder.append(i).append(") ").append(error.getDefaultMessage()).append("\n ");
		}
		return new Result<String>().error(builder.toString());
	}

	/*
	 * @ResponseStatus(HttpStatus.OK)
	 * 
	 * @ExceptionHandler(TemplateInputException.class)
	 * 
	 * @ResponseBody public Result<?> handle401(TemplateInputException e) { return
	 * new Result<String>().error(ResponseConstant.USER_NO_PERMITION); }
	 */
}